package controllers

import (
	"autoPage/models"
	"bytes"
	"errors"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/wxnacy/wgo/arrays"
	"time"

	"github.com/pquerna/ffjson/ffjson"
	"strconv"
	"strings"
)

type PageConfigController struct {
	BaseController
}

func (dc *PageConfigController) URLMapping() {
	dc.Mapping("List", dc.List)
	dc.Mapping("Add", dc.Add)
	dc.Mapping("Edit", dc.Edit)
	dc.Mapping("ClearCache", dc.ClearCache)
	dc.Mapping("Reset", dc.Reset)
}
func (dc *PageConfigController) Reset() {
	models.ClearCache()
	algoInfo := beego.AppConfig.String("SysInfo::algoInfo")
	algo_port := beego.AppConfig.String("SysInfo::algo_port")
	host_dir := beego.AppConfig.String("SysInfo::host_dir")
	algo_start_cmd := beego.AppConfig.String("SysInfo::algo_start_cmd")
	algo_start_envs := beego.AppConfig.String("SysInfo::algo_start_envs")

	var errarr []string
	sql := "update page_config set configJson = '" + algoInfo + "' ,configId = 'AlgoInfo' where id =11"
	err := dc.ExecuteNoquery(allinkstr, sql)
	if err != nil {
		errarr = append(errarr, err.Error())
		beego.Error("update page_config AlgoInfo failed: ", err.Error())
	} else {
		beego.Info("update page_config AlgoInfo success")
	}
	sql = "update page_config set configJson = '" + algo_port + "' ,configId = 'algo_port' where id =10"
	err = dc.ExecuteNoquery(allinkstr, sql)
	if err != nil {
		errarr = append(errarr, err.Error())
		beego.Error("update page_config algo_port failed: ", err.Error())
	} else {
		beego.Info("update page_config algo_port success")
	}
	sql = "update page_config set configJson = '" + host_dir + "' ,configId = 'host_dir' where id =9"
	err = dc.ExecuteNoquery(allinkstr, sql)
	if err != nil {
		errarr = append(errarr, err.Error())
		beego.Error("update page_config host_dir failed: ", err.Error())
	} else {
		beego.Info("update page_config host_dir success")
	}

	sql = "update page_config set configJson = '" + algo_start_cmd + "' ,configId = 'algo_start_cmd' where id =8"
	err = dc.ExecuteNoquery(allinkstr, sql)
	if err != nil {
		errarr = append(errarr, err.Error())
		beego.Error("update page_config algo_start_cmd failed: ", err.Error())
	} else {
		beego.Info("update page_config algo_start_cmd success")
	}

	sql = "update page_config set configJson = '" + algo_start_envs + "' ,configId = 'algo_start_envs' where id =7"
	err = dc.ExecuteNoquery(allinkstr, sql)
	if err != nil {
		errarr = append(errarr, err.Error())
		beego.Error("update page_config algo_start_envs failed: ", err.Error())
	} else {
		beego.Info("update page_config algo_start_envs success")
	}
	if len(errarr) > 0 {
		dc.ShowMsg("执行失败，"+strings.Join(errarr, "；"), "-1", 4)

	} else {
		dc.ShowMsg("数据初始化成功", "-1", 2)

	}
}
func (dc *PageConfigController) ClearCache() {
	err := models.ClearCache()
	if err == nil {
		dc.ShowMsg("删除成功！", "/pageconfig/list", 1)
	} else {
		dc.ShowMsg("删除成功！", "/pageconfig/list", 1)
	}
}

func GetConfigItems(configId string, kv map[string]interface{}) (string, error) {
	if strings.Trim(configId, " ") == "" {
		return "", errors.New("ConfigId is null")
	}
	configId = strings.TrimSpace(configId)
	var configItem []*models.ConfigItem
	pageConfig, err := models.GetPageConfigByConfigId(configId)
	if err != nil {
	} else {
		err := ffjson.Unmarshal([]byte(pageConfig.ConfigJson), &configItem)
		if err != nil {
			return "", err
		}
	}

	var buf bytes.Buffer
	for _, v := range configItem {
		buf.WriteString(GetFormHTMLItem(v, kv))
	}
	//GetListHTMLItem(configItem, table_ConfigAlgorithm)
	return buf.String(), nil
}

func GetFormHTMLItem(ci *models.ConfigItem, kv map[string]interface{}) string {
	var buf bytes.Buffer
	if  ci.Type == "subarr" {
		buf.WriteString(fmt.Sprintf(`<div class="form_row" name="%s">`, ci.Field+ci.Type))
	}else if ci.Type == "objarr"{

	} else {

		buf.WriteString(`<div class="form_row">`)

	}
	if ci.Type != "hidden" {
		if strings.TrimSpace(ci.Name) != ""  {
			if ci.Type == "objarr"{
				buf.WriteString(fmt.Sprintf(`<div class="form_row" ><label for="%s" class="form_arrText col-20">`, ci.Field))
			}else{
				buf.WriteString(fmt.Sprintf(`<label for="%s" class="form_labelText col-2">`, ci.Field))
			}

			if ci.AllowBlank != "true" {
				buf.WriteString(`<span class="required">*</span>`)
			}
			if ci.Type == "button" || ci.Type == "label" {
				buf.WriteString(`</label>`)
			} else {
				buf.WriteString(fmt.Sprintf(`%s：</label>`, ci.Name))
			}
			if ci.Type == "objarr"{
				buf.WriteString(`</div>`)
			}
		}
	}

	ops := strings.Trim(ci.Options, "")
	opss := strings.Split(ops, "|")
	var optsv interface{}
	if vv, ok := kv[ci.Field]; ok {
		optsv = vv
	}
	switch ci.Type {
	case "label":
		buf.WriteString(fmt.Sprintf(`<label name="%s">%s</label>`, ci.Field, ops))
	case "button":
		buf.WriteString(fmt.Sprintf(`<input type="button"  style="float:left" name="%s" value="%s"   width="%s" height="%s" />`, ci.Field, ci.Name, ci.Width, ci.Height))
	case "hidden":
		buf.WriteString(fmt.Sprintf(`<input type="hidden"  class="form_text col-6" name="%s"  `, ci.Field))
		if v, ok := kv[ci.Field]; ok {
			buf.WriteString(fmt.Sprintf(`value="%s"`, ToString(v)))
		}
		buf.WriteString(" />")
	case "img":
		buf.WriteString(fmt.Sprintf(`<img src="%s" style="float:left"  name="%s"  width="%s" height="%s" />`, ci.Options, ci.Field, ci.Width, ci.Height))
	case "number":
		buf.WriteString(fmt.Sprintf(`<input type="%s" name="%s" id="%s"  class="form_text col-7" `, ci.Type, ci.Field, ci.Field))
		if v, ok := kv[ci.Field]; ok {
			buf.WriteString(fmt.Sprintf(`value="%s"`, ToString(v)))
		}
		if ci.MaxLength > 0 {
			buf.WriteString(` maxlength=` + strconv.Itoa(ci.MaxLength))
		}
		if ci.ReadOnly == "true" {
			buf.WriteString(` readonly `)
		}
		if ci.AllowBlank != "true" {
			buf.WriteString(` required `)
		}
		if strings.TrimSpace(ci.Options) != "" {
			options := strings.Split(ci.Options, "|")
			if len(options) >= 1 {
				buf.WriteString(` min=` + options[0])
			}
			if len(options) >= 2 {
				buf.WriteString(` max=` + options[1])
			}
			if len(options) >= 3 {
				buf.WriteString(` step=` + options[2])
			}
		}
		buf.WriteString("></input>")
	case "float":
		fixNum := "2"
		if strings.TrimSpace(ci.Options) != "" {
			fixNum = strings.TrimSpace(ci.Options)
		}
		buf.WriteString(fmt.Sprintf(`<input type="text"   name="%s" id="%s" onkeyup="value=value.replace(/^\D*(\d*(?:\.\d{0,%s})?).*$/g, '$1')"  class="form_text col-7" `, ci.Field, ci.Field, fixNum))
		if v, ok := kv[ci.Field]; ok {
			buf.WriteString(fmt.Sprintf(`value="%s"`, ToString(v)))
		}
		if ci.ReadOnly == "true" {
			buf.WriteString(` readonly `)
		}
		if ci.AllowBlank != "true" {
			buf.WriteString(` required `)
		}
		if ci.MaxLength > 0 {
			buf.WriteString(` maxlength=` + strconv.Itoa(ci.MaxLength))
		}
		buf.WriteString("></input>")
	case "objarr": //对象数组
		if optsv == nil {
			buf.WriteString(fmt.Sprintf(`<div class="form_row" name="%s">`, ci.Field+ci.Type))
			buf.WriteString(`<div  style="display:inline;" class="col-20" >`)
			ss, _ := GetConfigItems(ci.Options, nil)
			buf.WriteString(ss)
			buf.WriteString(`<input type="button" class="form_row_btn" value="新增"
                                           onclick="CommonJs.add_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="删除"
                                           onclick="CommonJs.del_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="上移"
                                           onclick="CommonJs.up_tr(this)"/>`)
			buf.WriteString(`</div></div>`)
		} else {
			var mm []map[string]interface{}
			ffjson.Unmarshal([]byte(optsv.(string)), &mm)
			if mm == nil {
				buf.WriteString(fmt.Sprintf(`<div class="form_row" name="%s">`, ci.Field+ci.Type))
				buf.WriteString(`<div  style="display:inline;" class="col-20" >`)
				ss, _ := GetConfigItems(ci.Options, nil)
				buf.WriteString(ss)
				buf.WriteString(`<input type="button" class="form_row_btn" value="新增"
                                           onclick="CommonJs.add_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="删除"
                                           onclick="CommonJs.del_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="上移"
                                           onclick="CommonJs.up_tr(this)"/>`)
				buf.WriteString(`</div></div>`)

			} else {

				for i := 0; i < len(mm); i++ {
					buf.WriteString(fmt.Sprintf(`<div class="form_row" name="%s">`, ci.Field+ci.Type))
					buf.WriteString(`<div  style="display:inline;" class="col-20" >`)
					ss, _ := GetConfigItems(ci.Options, mm[i])
					buf.WriteString(ss)
					buf.WriteString(`<input type="button" class="form_row_btn" value="新增"
                                           onclick="CommonJs.add_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="删除"
                                           onclick="CommonJs.del_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="上移"
                                           onclick="CommonJs.up_tr(this)"/>`)
					buf.WriteString(`</div></div>`)


				}
			}
		}
	case "subarr":
		if optsv == nil {
			buf.WriteString(`<div  style="display:inline;" class="col-18" >`)

			ss, _ := GetConfigItems(ci.Options, nil)
			buf.WriteString(ss)
			buf.WriteString(`<input type="button" class="form_row_btn" value="新增"
                                           onclick="CommonJs.add_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="删除"
                                           onclick="CommonJs.del_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="上移"
                                           onclick="CommonJs.up_tr(this)"/>`)
			buf.WriteString(`</div>`)

		} else {
			mm := make([]string, 0)
			ffjson.Unmarshal([]byte(optsv.(string)), &mm)
			if len(mm) == 0 {
				buf.WriteString(`<div  style="display:inline;" class="col-18" >`)

				ss, _ := GetConfigItems(ci.Options, nil)
				buf.WriteString(ss)
				buf.WriteString(`<input type="button" class="form_row_btn" value="新增"
                                           onclick="CommonJs.add_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="删除"
                                           onclick="CommonJs.del_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="上移"
                                           onclick="CommonJs.up_tr(this)"/>`)
				buf.WriteString(`</div>`)

			} else {
				for i := 0; i < len(mm); i++ {
					if i >= 1 {

						buf.WriteString(fmt.Sprintf(`<div class="form_row" name="%s">`, ci.Field+ci.Type))
						if strings.TrimSpace(ci.Name) != "" {
							buf.WriteString(fmt.Sprintf(`<label for="%s" class="form_labelText col-2">`, ci.Field))
							if ci.AllowBlank != "true" {
								buf.WriteString(`<span class="required">*</span>`)
							}
							if ci.Type == "button" || ci.Type == "label" {
								buf.WriteString(`</label>`)
							} else {
								buf.WriteString(fmt.Sprintf(`%s：</label>`, ci.Name))
							}
						}
					}

					buf.WriteString(`<div  style="display:inline;" class="col-18" >`)
					kv := make(map[string]interface{})
					kv[ci.Field] = mm[i]
					ss, _ := GetConfigItems(ci.Options, kv)
					buf.WriteString(ss)
					buf.WriteString(`<input type="button" class="form_row_btn" value="新增"
                                           onclick="CommonJs.add_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="删除"
                                           onclick="CommonJs.del_tr(this)"/>
                                    <input type="button" class="form_row_btn" value="上移"
                                           onclick="CommonJs.up_tr(this)"/>`)
					buf.WriteString(`</div>`)
					if i == 0 {
						buf.WriteString(`</div>`)
					}
				}
			}
		}
	case "text", "date", "datetime", "url", "password":
		if ci.Width != "" {
			buf.WriteString(fmt.Sprintf(`<input type="%s" name="%s" id="%s"  class="form_text col-%s" `, ci.Type, ci.Field, ci.Field, ci.Width))
		} else {
			buf.WriteString(fmt.Sprintf(`<input type="%s" name="%s" id="%s"  class="form_text col-7" `, ci.Type, ci.Field, ci.Field))
		}
		if v, ok := kv[ci.Field]; ok {
			buf.WriteString(fmt.Sprintf(`value="%s"`, ToString(v)))
		}
		if ci.ReadOnly == "true" {
			buf.WriteString(` readonly `)
		}
		if ci.AllowBlank != "true" {
			buf.WriteString(` required `)
		}
		if ci.MaxLength > 0 {
			buf.WriteString(` maxlength=` + strconv.Itoa(ci.MaxLength))
		}
		buf.WriteString("></input>")
	case "textarea":
		if ci.Width != "" {
			buf.WriteString(fmt.Sprintf(`<textarea   name="%s" id="%s" class="form_textarea col-%v" `, ci.Field, ci.Field, ci.Width))
		} else {
			buf.WriteString(fmt.Sprintf(`<textarea   name="%s" id="%s" class="form_textarea col-7" `, ci.Field, ci.Field))
		}
		if ci.Height != "" {
			buf.WriteString(fmt.Sprintf(" height=%vpx", ci.Height))
		}
		if ci.MaxLength > 0 {
			buf.WriteString(fmt.Sprintf(` maxlength="%s"`, strconv.Itoa(ci.MaxLength)))
		}
		if ci.ReadOnly == "true" {
			buf.WriteString(` readonly `)
		}
		if ci.AllowBlank != "true" {
			buf.WriteString(` required `)
		}
		buf.WriteString(">")
		if v, ok := kv[ci.Field]; ok {
			buf.WriteString(ToString(v))
		}
		buf.WriteString("</textarea>")
	case "select":
		buf.WriteString(fmt.Sprintf(`<select name="%s" id="%s"   `, ci.Field, ci.Field))

		if ci.ReadOnly == "true" {
			buf.WriteString(` disabled `)
		}
		if ci.Width != "" {
			buf.WriteString(fmt.Sprintf(` class="form_text col-%s">`, ci.Width))

		} else {
			buf.WriteString(` class="form_text col-7">`)

		}
		for i := 0; i < len(opss); i++ {
			buf.WriteString(fmt.Sprintf(`<option value=%s`, opss[i]))
			if optsv != nil && optsv.(string) == opss[i] {
				buf.WriteString(` selected="selected"`)
			}
			buf.WriteString(fmt.Sprintf(`>%s</option>`, opss[i]))
		}

		buf.WriteString("</select>")
	case "radio":
		for i := 0; i < len(opss); i++ {
			buf.WriteString(fmt.Sprintf(`<input type="radio" value="%s"  name="%s"`, opss[i], ci.Field))
			if optsv == opss[i] {
				buf.WriteString(`checked="checked"`)
			}
			if ci.ReadOnly == "true" {
				buf.WriteString(` readonly `)
			}
			buf.WriteString(fmt.Sprintf(`/><label>%s</label>`, opss[i]))
		}
	case "checkbox":
		if len(opss) > 0 {
			var subv []string
			if optsv != nil {
				subv = strings.Split(optsv.(string), "|")
			}
			buf.WriteString("<p class='form_checkboxp col-7' >")
			for i := 0; i < len(opss); i++ {
				buf.WriteString(fmt.Sprintf(`<input type="checkbox" class="form_checkbox"  value="%s" name="%s"`, opss[i], ci.Field))
				if arrays.ContainsString(subv, opss[i]) >= 0 {
					buf.WriteString(`checked="checked"`)
				}
				if ci.ReadOnly == "true" {
					buf.WriteString(` readonly `)
				}
				buf.WriteString(fmt.Sprintf(` />%s`, opss[i]))
			}
			buf.WriteString("</p>")
		}

	default:
		return ""
	}
	if ci.Type!="objarr"{
		buf.WriteString("</div>")
	}

	return buf.String()
}

func (dc *PageConfigController) List() {
	fields := []string{"id", "configId", "configJson", "createtime",
		"lastmodifytime"}
	l, err := models.GetAllPageConfig(fields)
	if err != nil {
		dc.Data["list"] = nil
	} else {
		dc.Data["list"] = l
	}
	dc.Data["CurrentMenu"] = PAGECONFIG_MENU
	dc.Data["ActiveMenu"] = PAGECONFIG_MENU
	dc.TplName = "pageconfig/list.html"
}

func (dc *PageConfigController) Edit() {
	if dc.IsSubmit() {
		var e models.PageConfig
		var F models.ConfigItems
		if err := dc.ParseForm(&F); err != nil {
			dc.ShowMsg("修改表单失败，请重试!", "-1", 4)
			beego.Error("修改表单失败,", err.Error())
		} else {
			queryParams := dc.GetUrlQuery()
			e.Id, _ = strconv.ParseInt(queryParams.Get("id"), 10, 64)
			e.ConfigId = dc.Ctx.Request.Form["configId"][0]
			e.LastModifyTime = time.Now().Format(timefmt)

			var jsonArr []map[string]interface{}
			var fieldArr []string
			for i := 0; i < len(F.Field); i++ {
				m := make(map[string]interface{})
				if F.Field != nil {
					if arrays.Contains(fieldArr, F.Field[i]) >= 0 {
						err = errors.New("字段 " + F.Field[i] + "重复，请修改后重新提交")
						dc.ShowMsg("字段 "+F.Field[i]+"重复，请修改后重新提交", "-1", 4)
						beego.Error("字段 " + F.Field[i] + "重复，请修改后重新提交")
						return
					}
					fieldArr = append(fieldArr, F.Field[i])
					m["field"] = F.Field[i]
				}
				if F.Type != nil {
					m["type"] = F.Type[i]
				}
				if F.Name != nil {
					m["name"] = F.Name[i]
				}
				if F.Options != nil {
					if strings.TrimSpace(F.Options[i]) != "" {
						m["options"] = F.Options[i]
					}
				}
				if F.AllowBlank != nil {
					m["allowblank"] = F.AllowBlank[i]
				}
				if F.ReadOnly != nil {
					m["readonly"] = F.ReadOnly[i]
				}
				if F.MaxLength != nil {
					if strings.TrimSpace(strconv.Itoa(F.MaxLength[i])) != "" {
						m["maxlength"] = F.MaxLength[i]
					}
				}
				if F.Width != nil {
					if strings.TrimSpace(F.Width[i]) != "" {
						m["width"] = F.Width[i]
					}
				}
				if F.Height != nil {
					if strings.TrimSpace(F.Height[i]) != "" {
						m["height"] = F.Height[i]
					}
				}
				jsonArr = append(jsonArr, m)
			}
			jsonbytes, err := ffjson.Marshal(jsonArr)
			if err != nil {
				beego.Error("编辑失败，错误信息:", err.Error())
				dc.ShowMsg("修改失败了", "/pageconfig/list", 3)
			} else {
				e.ConfigJson = string(jsonbytes)
				err := models.UpdatePageConfigById(&e)
				if err != nil {
					beego.Error("pageconfig ：", err.Error())
					dc.ShowMsg("修改失败了", "/pageconfig/list", 1)
				} else {
					dc.ShowMsg("修改成功了", "/pageconfig/list", 1)
				}
			}
		}
	} else {
		_, actionName := dc.GetControllerAndAction()
		dc.Data["ACTION_NAME"] = actionName
		var id int64

		queryParams := dc.GetUrlQuery()
		id, _ = strconv.ParseInt(queryParams.Get("id"), 10, 64)

		data, _ := models.GetPageConfigById(id)
		var m []map[string]interface{}
		ffjson.Unmarshal([]byte(data.ConfigJson), &m)

		dc.Data["JsonArr"] = m
		dc.Data["CurrentMenu"] = PAGECONFIG_MENU
		dc.Data["ActiveMenu"] = PAGECONFIG_MENU

		dc.Data["Data"] = data
		dc.TplName = "pageconfig/form.html"
	}
}

//添加
func (dc *PageConfigController) Add() {
	if dc.IsSubmit() {

	} else {
		_, actionName := dc.GetControllerAndAction()
		dc.Data["ACTION_NAME"] = actionName
		dc.Data["CurrentMenu"] = PAGECONFIG_MENU
		dc.TplName = "pageconfig/form.html"
	}
}
